package com.javacv.plus.examples.service;

import com.javacv.plus.extensions.image.ImageProcessor;
import com.javacv.plus.extensions.image.ProcessorResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

@Slf4j
@Service
public class ImageService {

    private final Path tempDir;

    public ImageService() {
        this.tempDir = Paths.get(System.getProperty("java.io.tmpdir"), "javacv-plus");
        try {
            Files.createDirectories(tempDir);
        } catch (IOException e) {
            log.error("Failed to create temp directory", e);
        }
    }

    public String resizeImage(MultipartFile file, int width, int height) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".png");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .resize(width, height)
                .save(outputFile.getAbsolutePath());
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to resize image", e);
            throw new RuntimeException("Image resize failed", e);
        }
    }

    public String rotateImage(MultipartFile file, int angle) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".png");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .rotate(angle)
                .save(outputFile.getAbsolutePath());
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to rotate image", e);
            throw new RuntimeException("Image rotation failed", e);
        }
    }

    public String convertImage(MultipartFile file, String format) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + "." + format);
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .saveAs(outputFile.getAbsolutePath(), format);
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to convert image", e);
            throw new RuntimeException("Image conversion failed", e);
        }
    }

    public String compressImage(MultipartFile file, double quality) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".jpg");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .saveAs(outputFile.getAbsolutePath(), "jpg");
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to compress image", e);
            throw new RuntimeException("Image compression failed", e);
        }
    }

    public String addWatermark(MultipartFile file, MultipartFile watermark, String position) {
        try {
            File inputFile = saveTempFile(file);
            File watermarkFile = saveTempFile(watermark);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".png");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .addWatermark(watermarkFile.getAbsolutePath())
                .save(outputFile.getAbsolutePath());
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to add watermark", e);
            throw new RuntimeException("Watermark addition failed", e);
        }
    }

    public String blurImage(MultipartFile file, int radius) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".png");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .blur(radius)
                .save(outputFile.getAbsolutePath());
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to blur image", e);
            throw new RuntimeException("Image blur failed", e);
        }
    }

    public String sharpenImage(MultipartFile file, double amount) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".png");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .gaussianBlur(amount)
                .save(outputFile.getAbsolutePath());
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to sharpen image", e);
            throw new RuntimeException("Image sharpening failed", e);
        }
    }

    public String convertToGrayscale(MultipartFile file) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".png");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .grayscale()
                .save(outputFile.getAbsolutePath());
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to convert to grayscale", e);
            throw new RuntimeException("Grayscale conversion failed", e);
        }
    }

    public String cropImage(MultipartFile file, int x, int y, int width, int height) {
        try {
            File inputFile = saveTempFile(file);
            File outputFile = new File(tempDir.toFile(), UUID.randomUUID() + ".png");
            
            ProcessorResult result = ImageProcessor.of(inputFile.getAbsolutePath())
                .crop(x, y, width, height)
                .save(outputFile.getAbsolutePath());
            
            return result.getOutputPath();
        } catch (Exception e) {
            log.error("Failed to crop image", e);
            throw new RuntimeException("Image crop failed", e);
        }
    }

    private File saveTempFile(MultipartFile file) throws IOException {
        File tempFile = new File(tempDir.toFile(), UUID.randomUUID() + getFileExtension(file.getOriginalFilename()));
        file.transferTo(tempFile);
        return tempFile;
    }

    private String getFileExtension(String filename) {
        return filename != null && filename.contains(".") ? filename.substring(filename.lastIndexOf(".")) : "";
    }
} 